﻿using System;
using System.Collections.Generic;
using System.IO;

namespace JavaVirtualMachine
{
    public static class FileStreams
    {
        private static Dictionary<string, Stream> streams = new Dictionary<string, Stream>();
        private static Dictionary<int, Image_> images = new Dictionary<int, Image_>();
        private static StreamReader ConsoleInputReader = new StreamReader(Console.OpenStandardInput());
        private static Stream ConsoleOutputStream = Console.OpenStandardOutput();
        private static Stream ConsoleErrorStream = Console.OpenStandardError();

        public static void AddImage(int key,Image_ image)
        {
            images.Add(key, image);
        }

        public static Image_ GetImage(int key)
        {
            if (images.ContainsKey(key))
                return images[key];
            return null;
        }

        public static void Dispose()
        {
            foreach (var item in streams)
            {
                item.Value.Dispose();
            }
            streams.Clear();
        }

        public static bool OpenRead(string file)
        {
            try
            {
                if (streams.ContainsKey(file))
                {
                    streams[file].Position = 0;
                    return true;
                }

                Stream stream = null;
                if (File.Exists(file))
                {
                    stream = File.OpenRead(file);
                }
                else
                {
                    stream = JarFile.GetReStream(file);
                }
                if (stream != null)
                {
                    streams.Add(file, stream);
                    return true;
                }
                return false;
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("File Not Found Exception:  " + file);
                return false;
            }
        }

        public static int ReadBytes(string file, Span<byte> span)
        {
            Stream fileStream = streams[file];
            return fileStream.Read(span);
        }

        public static int ReadBytesFromConsole(Span<byte> span)
        {
            return ConsoleInputReader.BaseStream.Read(span);
        }

        public static int AvailableBytes(string file)
        {
            Stream fileStream = streams[file];
            return (int)(fileStream.Length - fileStream.Position);
        }

        public static long GetLength(string file)
        {
            Stream fileStream = streams[file];
            return fileStream.Length;
        }

        public static int AvailableBytesFromConsole()
        {
            return 0;
        }

        public static bool OpenWrite(string file)
        {
            try
            {
                FileStream fileStream = File.Open(file, FileMode.Open);
                streams.Add(file, fileStream);
                return true;
            }
            catch (FileNotFoundException)
            {
                return false;
            }
        }

        public static void WriteBytes(string file, ReadOnlySpan<byte> span, bool append)
        {
            Stream fileStream = streams[file];
            if(append)
            {
                fileStream.Position = fileStream.Length;
                fileStream.Write(span);
            }
            else
            {
                fileStream.Position = 0;
                fileStream.Write(span);
            }
            fileStream.Flush();
        }

        public static void WriteBytesToConsole(ReadOnlySpan<byte> span)
        {
            Console.ForegroundColor = ConsoleColor.White;
            ConsoleOutputStream.Write(span);
        }

        public static void WriteBytesToError(ReadOnlySpan<byte> span)
        {
            Console.ForegroundColor = ConsoleColor.White;
            ConsoleErrorStream.Write(span);
        }

        public static void Close(string file)
        {
            Stream fileStream = streams[file];
            fileStream.Close();
            streams.Remove(file);
        }

        public static long Skip(string file,long n)
        {
            Stream fileStream = streams[file];
            return fileStream.Seek(n,SeekOrigin.Current);
        }
    }
}
